package com.ayla.demo.widgets

import android.graphics.Rect
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager


class StaggeredItemDecoration(
    private val left: Int,
    private val right: Int,
    private val top: Int,
    private val bottom: Int,
    private val horizontal: Int,
    private val vertical: Int,
) : RecyclerView.ItemDecoration() {

    private var spanCount = 0
    private var itemCount = 0

    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        val layoutManager = parent.layoutManager
        if (layoutManager != null && layoutManager is StaggeredGridLayoutManager) {
            spanCount = layoutManager.spanCount
            itemCount = layoutManager.itemCount
            if (layoutManager.orientation == StaggeredGridLayoutManager.VERTICAL) {
                handleVertical(outRect, view, parent)
            } else {
                handleHorizontal(outRect, view, parent)
            }
        }
    }

    private fun handleHorizontal(outRect: Rect, view: View, parent: RecyclerView) {
        val params = view.layoutParams as StaggeredGridLayoutManager.LayoutParams
        val spanIndex = params.spanIndex
        val adapterPos: Int = parent.getChildAdapterPosition(view)
        val sizeAvg = ((vertical * (spanCount - 1) + top + bottom) * 1f / spanCount).toInt()
        val top = computeTop(spanIndex, sizeAvg)
        val bottom = computeBottom(spanIndex, sizeAvg)
        outRect.top = top
        outRect.bottom = bottom
        outRect.left = horizontal / 2
        outRect.right = horizontal / 2
        if (isFirstRaw(adapterPos)) {
            outRect.left = left
        }
        if (isLastRaw(spanIndex)) {
            outRect.right = right
        }
    }

    private fun handleVertical(outRect: Rect, view: View, parent: RecyclerView) {
        val params = view.layoutParams as StaggeredGridLayoutManager.LayoutParams
        val spanIndex = params.spanIndex
        val adapterPos: Int = parent.getChildAdapterPosition(view)
        val sizeAvg = ((horizontal * (spanCount - 1) + left + right) * 1f / spanCount).toInt()
        val left = computeLeft(spanIndex, sizeAvg)
        val right = computeRight(spanIndex, sizeAvg)
        outRect.left = left
        outRect.right = right
        outRect.top = vertical / 2
        outRect.bottom = vertical / 2
        if (isFirstRaw(adapterPos)) {
            //第一行
            outRect.top = top
        }
        if (isLastRaw(spanIndex)) {
            //最后一行
            outRect.bottom = bottom
        }
    }

    /**
     * 判断Item是否是第一行
     * @param adapterPos item对应的Adapter position
     */
    private fun isFirstRaw(adapterPos: Int): Boolean {
        return adapterPos < spanCount
    }

    /**
     * 判断Item是否是第一行
     * @param spanIndex item对应的spanIndex
     */
    private fun isLastRaw(spanIndex: Int): Boolean {
        return spanIndex >= itemCount - spanCount
    }

    /**
     * 计算Item的左边Decoration(outRect.left)尺寸,当orientation为Vertical时调用
     *
     * @param spanIndex 需要计算的Item对应的spanIndex
     * @param sizeAvg   每个Item需要填充的尺寸
     * @return outRect.left
     */
    private fun computeLeft(spanIndex: Int, sizeAvg: Int): Int {
        return when {
            spanIndex == 0 -> {
                left
            }
            spanIndex >= spanCount / 2 -> {
                //从右边算起
                sizeAvg - computeRight(spanIndex, sizeAvg)
            }
            else -> {
                //从左边算起
                horizontal - computeRight(spanIndex - 1, sizeAvg)
            }
        }
    }

    /**
     * 计算Item的右边Decoration(outRect.right)尺寸,当orientation为Vertical时调用
     *
     * @param spanIndex 需要计算的Item对应的spanIndex
     * @param sizeAvg   每个Item需要填充的尺寸
     * @return outRect.right
     */
    private fun computeRight(spanIndex: Int, sizeAvg: Int): Int {
        return when {
            spanIndex == spanCount - 1 -> {
                right
            }
            spanIndex >= spanCount / 2 -> {
                //从右边算起
                horizontal - computeLeft(spanIndex + 1, sizeAvg)
            }
            else -> {
                //从左边算起
                sizeAvg - computeLeft(spanIndex, sizeAvg)
            }
        }
    }

    /**
     * 计算Item的顶部边Decoration(outRect.Top)尺寸,当orientation为Horizontal时调用
     *
     * @param spanIndex 需要计算的Item对应的spanIndex
     * @param sizeAvg   每个Item需要填充的尺寸
     * @return outRect.top
     */
    private fun computeTop(spanIndex: Int, sizeAvg: Int): Int {
        return when {
            spanIndex == 0 -> {
                top
            }
            spanIndex >= spanCount / 2 -> {
                //从底部算起
                sizeAvg - computeBottom(spanIndex, sizeAvg)
            }
            else -> {
                //从顶端算起
                vertical - computeBottom(spanIndex - 1, sizeAvg)
            }
        }
    }

    /**
     * 计算Item的底部Decoration(outRect.bottom)尺寸,当orientation为Horizontal时调用
     *
     * @param spanIndex 需要计算的Item对应的spanIndex
     * @param sizeAvg   每个Item需要填充的尺寸
     * @return outRect.bottom
     */
    private fun computeBottom(spanIndex: Int, sizeAvg: Int): Int {
        return when {
            spanIndex == spanCount - 1 -> {
                bottom
            }
            spanIndex >= spanCount / 2 -> {
                //从底部算起
                vertical - computeTop(spanIndex + 1, sizeAvg)
            }
            else -> {
                //从顶端算起
                sizeAvg - computeTop(spanIndex, sizeAvg)
            }
        }
    }

}